<html>
<head>
    <script>
        function testToStringAndValueOf(title, type, object)
        {
            var results = [ title ];
            try { addResult(type + ' : ' + object); } catch(e) { addResult(e); }
            try { addResult('[' + type + '] : ' + [object]); } catch(e) { addResult(e); }
            try { addResult('String(' + type + ') : ' + String(object)); } catch(e) { addResult(e); }
            try { addResult('String([' + type + ']) : ' + String([object])); } catch(e) { addResult(e); }
            try { addResult(type + '.toString : ' + object.toString); } catch(e) { addResult(e); }
            try { var toString = object.toString; addResult(type + '.toString() (cached in variable) : ' + toString()); } catch(e) { addResult(e); }
            try { addResult(type + '.toString() : ' + object.toString()); } catch(e) { addResult(e); }
            try { addResult('[' + type + '].toString() : ' + [object].toString()); } catch(e) { addResult(e); }
            try { addResult(type + '.valueOf() : ' + object.valueOf()); } catch(e) { addResult(e); }
            try { addResult('[' + type + '].valueOf() : ' + [object].valueOf()); } catch(e) { addResult(e); }
            return results.join('<br>') + '<br><br>';

            function addResult(result)
            {
                results.push(result);
            }
        }

        function test(resultsElement, type, object)
        {
            var results = '';
            results += testToStringAndValueOf('Unmodified ' + type, type, object);

            object.toString = function() { return "toString" }
            object.valueOf = function() { return "valueOf" }
            results += testToStringAndValueOf(type + ' with modified toString and valueOf', type, object);

            object.toString = function() { return new Object(); }
            results += testToStringAndValueOf(type + ' with modified toString that returns an Object', type, object);

            object.toString = function() { return 'toString'; }
            object.valueOf = function() { return new Object(); }
            results += testToStringAndValueOf(type + ' with modified valueOf that returns an Object', type, object);

            object.toString = function() { return new Object(); }
            results += testToStringAndValueOf(type + ' with modified toString and valueOf that returns an Object', type, object);

            object.toString = function() { throw "Exception"; }
            object.valueOf = function() { return "valueOf"; }
            results += testToStringAndValueOf(type + ' with modified toString that throws an exception', type, object);

            object.toString = function() { return 'toString'; }
            object.valueOf = function() { throw "Exception"; }
            results += testToStringAndValueOf(type + ' with modified valueOf that throws an exception', type, object);

            object.toString = function() { throw "Exception"; }
            object.valueOf = function() { throw "Exception"; }
            results += testToStringAndValueOf(type + ' with modified toString an valueOf that throw exceptions', type, object);

            resultsElement.innerHTML += results + '<br>';
        }

        function runTests()
        {
            if (window.testRunner)
                testRunner.dumpAsText();

            var resultsElement = document.getElementById('results');
            test(resultsElement, 'span', document.createElement('span'));
            test(resultsElement, 'window', window);
            test(resultsElement, 'Navigator', window.navigator);
            test(resultsElement, 'History', window.history);
            test(resultsElement, 'Selection', window.getSelection());
        }
    </script>
</head>
<body onload="runTests();">
<div id="results">
</div>
</body>
</html>
